#include "stdafx.h"
#include "CppUnitTest.h"

#include <HSModel/Triangle3D.h>
#include <HSModel/Model3D.h>
#include <HSModel/TextureUtils.h>
#include <HSModel/GeometryUtils.h>

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace HSModelTests
  {
  TEST_CLASS(TextureTests)
    {
    public:

      TEST_METHOD(ShouldApplyTexturesCorrectlyOnRectangle)
        {
        Model3D model;
        Point3DID p1 = model.AddPoint(TVector3(1.0, 1.0, 0.0));
        Point3DID p2 = model.AddPoint(TVector3(3.0, 1.0, 0.0));
        Point3DID p3 = model.AddPoint(TVector3(1.0, 3.0, 0.0));
        Point3DID p4 = model.AddPoint(TVector3(3.0, 3.0, 0.0)); 

        Triangle3DID triangle_down_id = model.AddTriangle(p1, p2, p3);
        Triangle3DID triangle_up_id = model.AddTriangle(p2, p3, p4);

        Textures::ApplyTextures(model);
        
        TVector2 down_uv_actual_0 = triangle_down_id.GetTriangle().GetPointUV(0);
        TVector2 down_uv_actual_1 = triangle_down_id.GetTriangle().GetPointUV(1);
        TVector2 down_uv_actual_2 = triangle_down_id.GetTriangle().GetPointUV(2);

        TVector2 up_uv_actual_0 = triangle_up_id.GetTriangle().GetPointUV(0);
        TVector2 up_uv_actual_1 = triangle_up_id.GetTriangle().GetPointUV(1);
        TVector2 up_uv_actual_2 = triangle_up_id.GetTriangle().GetPointUV(2);
 
        TVector2 down_uv_expected_0 = TVector2(0,0);
        TVector2 down_uv_expected_1 = TVector2(1,0);
        TVector2 down_uv_expected_2 = TVector2(0,1);

        TVector2 up_uv_expected_0 = TVector2(1,0);
        TVector2 up_uv_expected_1 = TVector2(0,1);
        TVector2 up_uv_expected_2 = TVector2(1,1);

        Assert::AreEqual(down_uv_expected_0.X(), down_uv_actual_0.X());
        Assert::AreEqual(down_uv_expected_0.Y(), down_uv_actual_0.Y());
        Assert::AreEqual(down_uv_expected_1.X(), down_uv_actual_1.X());
        Assert::AreEqual(down_uv_expected_1.Y(), down_uv_actual_1.Y());
        Assert::AreEqual(down_uv_expected_2.X(), down_uv_actual_2.X());
        Assert::AreEqual(down_uv_expected_2.Y(), down_uv_actual_2.Y());

        Assert::AreEqual(up_uv_expected_0.X(), up_uv_actual_0.X());
        Assert::AreEqual(up_uv_expected_0.Y(), up_uv_actual_0.Y());
        Assert::AreEqual(up_uv_expected_1.X(), up_uv_actual_1.X());
        Assert::AreEqual(up_uv_expected_1.Y(), up_uv_actual_1.Y());
        Assert::AreEqual(up_uv_expected_2.X(), up_uv_actual_2.X());
        Assert::AreEqual(up_uv_expected_2.Y(), up_uv_actual_2.Y());
        }

      TEST_METHOD(ShouldApplyTexturesCorrectlyOnRhombus)
        {
        //  *****X*****
        //  *  X   X  *
        //  * X     X *
        //  X         X    
        //  * X     X *
        //  *  X   X  *
        //  *****X*****
        Model3D model;
        Point3DID p1 = model.AddPoint(TVector3(8.0, 2.0, 0.0));
        Point3DID p2 = model.AddPoint(TVector3(5.0, 5.0, 0.0));
        Point3DID p3 = model.AddPoint(TVector3(11.0, 5.0, 0.0));
        Point3DID p4 = model.AddPoint(TVector3(8.0, 8.0, 0.0)); 

        Triangle3DID triangle_down_id = model.AddTriangle(p1, p2, p3);
        Triangle3DID triangle_up_id = model.AddTriangle(p2, p3, p4);

        Textures::ApplyTextures(model);

        TVector2 down_uv_actual_0 = triangle_down_id.GetTriangle().GetPointUV(0);
        TVector2 down_uv_actual_1 = triangle_down_id.GetTriangle().GetPointUV(1);
        TVector2 down_uv_actual_2 = triangle_down_id.GetTriangle().GetPointUV(2);

        TVector2 up_uv_actual_0 = triangle_up_id.GetTriangle().GetPointUV(0);
        TVector2 up_uv_actual_1 = triangle_up_id.GetTriangle().GetPointUV(1);
        TVector2 up_uv_actual_2 = triangle_up_id.GetTriangle().GetPointUV(2);

        TVector2 down_uv_expected_0 = TVector2(0.5, 0.0);
        TVector2 down_uv_expected_1 = TVector2(0.0, 0.5);
        TVector2 down_uv_expected_2 = TVector2(1.0, 0.5);

        TVector2 up_uv_expected_0 = TVector2(0.0,0.5);
        TVector2 up_uv_expected_1 = TVector2(1.0,0.5);
        TVector2 up_uv_expected_2 = TVector2(0.5, 1.0);

        Assert::AreEqual(down_uv_expected_0.X(), down_uv_actual_0.X());
        Assert::AreEqual(down_uv_expected_0.Y(), down_uv_actual_0.Y());
        Assert::AreEqual(down_uv_expected_1.X(), down_uv_actual_1.X());
        Assert::AreEqual(down_uv_expected_1.Y(), down_uv_actual_1.Y());
        Assert::AreEqual(down_uv_expected_2.X(), down_uv_actual_2.X());
        Assert::AreEqual(down_uv_expected_2.Y(), down_uv_actual_2.Y());

        Assert::AreEqual(up_uv_expected_0.X(), up_uv_actual_0.X());
        Assert::AreEqual(up_uv_expected_0.Y(), up_uv_actual_0.Y());
        Assert::AreEqual(up_uv_expected_1.X(), up_uv_actual_1.X());
        Assert::AreEqual(up_uv_expected_1.Y(), up_uv_actual_1.Y());
        Assert::AreEqual(up_uv_expected_2.X(), up_uv_actual_2.X());
        Assert::AreEqual(up_uv_expected_2.Y(), up_uv_actual_2.Y());
        }



    };
  }